home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 18 / AMIGAplus Sonderheft 18 (1999)(ICP)(DE)[!].iso / PD / Anwendungen / FS1541-13 / disk.c < prev    next >
C/C++ Source or Header  |  1999-01-03  |  8KB  |  403 lines

  1.  
  2. /*
  3.  * FS1541 - basic disk interaction routines
  4.  *
  5.  * Copyright (C) 1996 - 1998 Michael Krause
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20.  */
  21.  
  22. #include <string.h>
  23.  
  24. #include <exec/types.h>
  25. #include <exec/execbase.h>
  26. #include <exec/memory.h>
  27. #include <exec/ports.h>
  28. #include <dos/dos.h>
  29. #include <intuition/intuition.h>
  30. #include <devices/timer.h>
  31.  
  32. #include <proto/exec.h>
  33. #include <proto/intuition.h>
  34.  
  35. #include "disk.h"
  36. #include "volume.h"
  37.  
  38. LONG numsofterrors = 0;
  39. static struct MsgPort *diskport;
  40. struct IOExtTD *diskreq;
  41. BOOL autoscan = TRUE;
  42.  
  43. struct MsgPort *dpsender;
  44.  
  45. static UBYTE *diskimage;
  46. static int diskscanned;
  47. static BYTE sectab[683];
  48. static int curblk = 357; /* Preloading starts at 18,0 = BAM */
  49. static int devopen = 0;
  50. ULONG chgcount;
  51.  
  52. static BOOL ignoreall, abortall;
  53.  
  54. struct IntuitionBase *IntuitionBase;
  55.  
  56. int wprotected=FALSE, hardwprot=FALSE;
  57.  
  58. static void cacheblock(ULONG n, BOOL write);
  59.  
  60. /* ErrorReq() return codes */
  61. #define REQ_RETRY         1
  62. #define REQ_IGNORE        2
  63. #define REQ_IGNORE_ALL    3
  64. #define REQ_ABORT_ALL     0
  65.  
  66. /*-------------------------------------------------------------------------*/
  67.  
  68. LONG InitDiskSS(STRPTR device, ULONG unit, ULONG flags)
  69. {
  70.     LONG error = 0;
  71.  
  72.     if((diskimage = AllocVec(D64_SIZE, MEMF_PUBLIC)))
  73.     {
  74.         if((diskport = CreateMsgPort()))
  75.         {
  76.             if((diskreq = CreateIORequest(diskport, sizeof(struct IOExtTD))))
  77.             {
  78.                 if((devopen = (!OpenDevice(device,unit,(struct IORequest *)diskreq,flags))))
  79.                 {
  80.     
  81.                     return(0);
  82.     
  83.                 } else error = ERROR_DEVICE_NOT_MOUNTED;
  84.             } else error = ERROR_NO_FREE_STORE;
  85.         } else error = ERROR_NO_FREE_STORE;
  86.     } else error = ERROR_NO_FREE_STORE;
  87.  
  88.     QuitDiskSS();
  89.     return(error);
  90. }
  91.  
  92. void QuitDiskSS(void)
  93. {
  94.     if(devopen)
  95.         CloseDevice((struct IORequest*)diskreq);
  96.  
  97.     if(diskreq)
  98.         DeleteIORequest(diskreq);
  99.  
  100.     if(diskport)
  101.         DeleteMsgPort(diskport);
  102.  
  103.     if(diskimage)
  104.         FreeVec(diskimage);
  105. }
  106.  
  107. /*-------------------------------------------------------------------------*/
  108.  
  109. void ResetDisk(void)
  110. {
  111.     diskscanned = !autoscan;
  112.  
  113.     memset(sectab, SEC_NOT_LOADED, 683);
  114.  
  115.     curblk = 357;
  116.  
  117.     abortall = FALSE;
  118.     ignoreall = FALSE;
  119.  
  120.     diskreq->iotd_Req.io_Command = TD_CHANGENUM;
  121.     diskreq->iotd_Req.io_Flags = IOF_QUICK;
  122.     DoIO((struct IORequest*)diskreq);
  123.     chgcount = diskreq->iotd_Req.io_Actual;
  124.  
  125.     diskreq->iotd_Req.io_Command = ETD_CLEAR;
  126.     diskreq->iotd_Count = chgcount;
  127.     diskreq->iotd_Req.io_Flags = IOF_QUICK;
  128.     DoIO((struct IORequest*)diskreq);
  129.  
  130.     diskreq->iotd_Req.io_Command = TD_PROTSTATUS;
  131.     diskreq->iotd_Req.io_Flags = IOF_QUICK;
  132.     DoIO((struct IORequest*)diskreq);
  133.     hardwprot = diskreq->iotd_Req.io_Actual;
  134. }
  135.  
  136. /* Asynchronous disk preloader */
  137. BOOL LoadDisk(void)
  138. {
  139.     if(!diskscanned && curvolumenode && autoscan)
  140.     {
  141.         int readblk;
  142.  
  143.         for(readblk=curblk;readblk<683;readblk++)
  144.             if(sectab[readblk] == SEC_NOT_LOADED)
  145.                 break;
  146.  
  147.         if(readblk == 683)
  148.         {
  149.             if(curblk == 0)
  150.             {
  151.                 /* Loading finished - switch off motor. */
  152.                 diskreq->iotd_Req.io_Command = TD_MOTOR;
  153.                 diskreq->iotd_Req.io_Flags = 0;
  154.                 diskreq->iotd_Req.io_Length = 0;
  155.                 DoIO((struct IORequest*)diskreq);
  156.                 diskscanned = TRUE;
  157.                 return(TRUE);
  158.             }
  159.             else
  160.                 curblk = 0;
  161.  
  162.             return(FALSE);
  163.         }
  164.  
  165.         curblk = readblk;
  166.         cacheblock(readblk, FALSE);
  167.  
  168.         return(FALSE);
  169.  
  170.     } else return(TRUE);
  171. }
  172.  
  173. void MotorOff(void)
  174. {
  175.     if(diskscanned && CheckIO((struct IORequest*)UDStimer))
  176.     {
  177.         diskreq->iotd_Req.io_Command = ETD_UPDATE;
  178.         diskreq->iotd_Req.io_Flags = 0;
  179.         DoIO((struct IORequest*)diskreq);
  180.  
  181.         diskreq->iotd_Req.io_Command = TD_MOTOR;
  182.         diskreq->iotd_Req.io_Flags = 0;
  183.         diskreq->iotd_Req.io_Length = 0;
  184.         DoIO((struct IORequest*)diskreq);
  185.     }
  186. }
  187.  
  188. /*-------------------------------------------------------------------------*/
  189.  
  190. static LONG ts2block(UBYTE t, UBYTE s)
  191. {
  192.     if(t<1)
  193.     {
  194.         return(-1);
  195.     }
  196.     else if(t<=17)
  197.     {
  198.         if(s>21)
  199.             return(-1);
  200.         else
  201.             return(21*(t-1) + s);
  202.     }
  203.     else if(t<=24)
  204.     {
  205.         if(s>19)
  206.             return(-1);
  207.         else
  208.             return(21*17 + 19*(t-18) + s);
  209.     }
  210.     else if(t<=30)
  211.     {
  212.         if(s>18)
  213.             return(-1);
  214.         else
  215.             return(21*17 + 19*7 + 18*(t-25) + s);
  216.     }
  217.     else if(t<=35)
  218.     {
  219.         if(s>17)
  220.             return(-1);
  221.         else
  222.             return(21*17 + 19*7 + 18*6 + 17*(t-31) + s);
  223.     }
  224.     else
  225.         return(-1);
  226. }
  227.  
  228. int
  229. SectorsOnTrack (BYTE track)
  230. {
  231.     if(track < 1)
  232.         return 0;
  233.     if(track < 18)
  234.         return 21;
  235.     if(track < 25)
  236.         return 19;
  237.     if(track < 31)
  238.         return 18;
  239.     if(track < 36)
  240.         return 17;
  241.     return 0;
  242. }
  243.  
  244. UWORD
  245. Block2TS (UWORD blk)
  246. {
  247.     UWORD t,s,i,b=0;
  248.  
  249.     for (t=1;t<36;t++)
  250.     {
  251.         i=SectorsOnTrack(t);
  252.         for (s=0;s<i;s++)
  253.         {
  254.             if (b==blk) return ((t<<8)|s);
  255.             b++;
  256.         }
  257.     }
  258.     return (0);
  259. }
  260.  
  261. struct DataBlock *getblock_ts(UBYTE t, UBYTE s)
  262. {
  263.     LONG blk = ts2block(t, s);
  264.  
  265.     if(blk>=0)
  266.         return(getputblock(blk, FALSE));
  267.     else
  268.         return(NULL);
  269. }
  270.  
  271. struct DataBlock *putblock_ts(UBYTE t, UBYTE s, APTR data)
  272. {
  273.     LONG blk = ts2block(t, s);
  274.  
  275.     if(blk>=0)
  276.     {
  277.         CopyMem(data, diskimage+(blk*256), 256);
  278.         return(getputblock(blk, TRUE));
  279.     }
  280.     else
  281.         return(NULL);
  282. }
  283.  
  284. static int
  285. ErrorReq (ULONG blk)
  286. {
  287.     static struct EasyStruct req = {
  288.         sizeof(struct EasyStruct),
  289.         0,
  290.         "FS1541 Error",
  291.         "Volume %s has a\nread/write error on\ntrack %ld, sector %ld.",
  292.         "Retry|Ignore|Ignore All|Abort All" /* see REQ_ defines at the top of the file */
  293.     };
  294.     struct Process *pr = dpsender->mp_SigTask;
  295.     int x;
  296.  
  297.     if(!curvolumenode)
  298.         return -1;
  299.  
  300.     if(abortall)
  301.         return REQ_ABORT_ALL;
  302.     
  303.     if(ignoreall)
  304.         return REQ_IGNORE_ALL;
  305.     
  306.     if(!(IntuitionBase = (struct IntuitionBase*)OpenLibrary("intuition.library",36)))
  307.         return -1;
  308.  
  309.     if((dpsender->mp_Flags & PF_ACTION) != PA_SIGNAL
  310.        || pr->pr_Task.tc_Node.ln_Type != NT_PROCESS
  311.        || pr->pr_WindowPtr != (APTR)-1) {
  312.         UWORD ts = Block2TS(blk);
  313.         ULONG args[3] = {
  314.             (ULONG)&curvolumenode->name[1],
  315.             (ULONG)(ts>>8),
  316.             (ULONG)(ts&0xFF)
  317.         };
  318.         
  319.         x = EasyRequestArgs(NULL, &req, NULL, args);
  320.     } else {
  321.         x = REQ_ABORT_ALL;
  322.     }
  323.     
  324.     CloseLibrary((struct Library*)IntuitionBase);
  325.     return x;
  326. }
  327.  
  328. struct DataBlock *
  329. getputblock (ULONG blk,
  330.          BOOL write)
  331. {
  332.     int retry;
  333.     int num = REQ_IGNORE;
  334.  
  335.     if(blk >= 683)
  336.         return NULL;
  337.  
  338.     if(write)
  339.         cacheblock(blk, TRUE);
  340.  
  341.     switch(sectab[blk]) {
  342.     case SEC_NOT_LOADED:
  343.         do {
  344.             retry = 10;
  345.             while (retry) {
  346.                 curblk = blk;
  347.                 cacheblock(blk, FALSE);
  348.                 if(sectab[blk] == SEC_OK)
  349.                     return (struct DataBlock*)(diskimage+(blk*256));
  350.                 retry--;
  351.             }
  352.         } while((num = ErrorReq(blk)) == REQ_RETRY);
  353.         /* fall through */
  354.  
  355.     case SEC_ERROR:
  356.     default:
  357.         switch(num) {
  358.         case REQ_IGNORE_ALL:
  359.             ignoreall = TRUE;
  360.             /* fall through */
  361.         case REQ_IGNORE:
  362.             return (struct DataBlock*)(diskimage+(blk*256));
  363.  
  364.         case REQ_ABORT_ALL:
  365.         default:
  366.             abortall = TRUE;
  367.             return NULL;
  368.         }
  369.         
  370.         return NULL;
  371.         
  372.     case SEC_OK:
  373.         return (struct DataBlock*)(diskimage+(blk*256));
  374.     }
  375. }
  376.  
  377. static void
  378. cacheblock (ULONG n,
  379.         BOOL write)
  380. {
  381.     diskreq->iotd_Count = chgcount;
  382.     diskreq->iotd_Req.io_Command = write ? ETD_WRITE : ETD_READ;
  383.     diskreq->iotd_Req.io_Flags = 0;
  384.     diskreq->iotd_Req.io_Data = diskimage+(n*256);
  385.     diskreq->iotd_Req.io_Offset = 256*n;
  386.     diskreq->iotd_Req.io_Length = 256;
  387.  
  388.     if(!DoIO((struct IORequest*)diskreq)) {
  389.         sectab[n] = SEC_OK;
  390.     } else {
  391.         sectab[n] = SEC_ERROR;
  392.         numsofterrors++;
  393.  
  394.         if(!curvolumenode) {
  395.             /* Switch off the motor, unread/writable disk. */
  396.             diskreq->iotd_Req.io_Command = TD_MOTOR;
  397.             diskreq->iotd_Req.io_Flags = 0;
  398.             diskreq->iotd_Req.io_Length = 0;
  399.             DoIO((struct IORequest*)diskreq);
  400.         }
  401.     }
  402. }
  403.